#include "tthreadpool.h"
using namespace std;
namespace tlib
{
TThreadPool::TThreadPool() :
	m_bRunning(false)
{

}

TThreadPool::~TThreadPool()
{
	if (m_bRunning)
		Stop();
}

void TThreadPool::runInThread()
{
	while (m_bRunning)
	{
		TTask task = Take();
		task();
	}
}

void TThreadPool::Start(int numThreads)
{
	m_bRunning = true;
	for (int i = 0; i < numThreads; i++)
	{
		TThread* thread = new TThread;
		thread->Run(bind(&TThreadPool::runInThread, this));
		m_threads.push_back(thread);
	}
}

void TThreadPool::Stop()
{
	{
		TAutoLock lock(&m_mutex);
		m_bRunning = false;
		m_bNotEmpty.NotifyAll();
	}
	for (vector<TThread*>::iterator it = m_threads.begin(); it != m_threads.end(); it++)
	{
		(*it)->Join();
	}
}

void TThreadPool::Run(TTask tk)
{
	TAutoLock lock(&m_mutex);
	m_tasks.push_back(tk);
	m_bNotEmpty.Notify();
}

TTask TThreadPool::Take()
{
	TAutoLock lock(&m_mutex);
	while (m_tasks.empty() && m_bRunning)
	{
		m_bNotEmpty.Wait(&m_mutex);
	}
	TTask task;
	if (!m_tasks.empty())
	{
		task = m_tasks.front();
		m_tasks.pop_front();
	}
	return task;
}
}
